﻿using System;

/*
 * 创建人：
 * 
 * 时间：
 * 
 * 说明：
 * 
 * 
 * 修改说明：
 * 
 * 
 */


namespace ConsoleTest.ChapterSeven
{
    public class Reflection
    {
        /// <summary>
        /// 对载入当前应用程序域的所有程序及进行反射
        /// </summary>
        public static void ReflectionNowAppDomain()
        {
            System.Reflection.Assembly ass = System.Reflection.Assembly.GetExecutingAssembly();
            foreach (System.Type t in ass.GetTypes())
            {
                if (t.IsClass)
                {
                    System.Console.WriteLine("Class :" + t);
                    System.Console.WriteLine("---------------------------------------");
                    foreach (System.Reflection.MethodInfo minfo in t.GetMethods())
                    {
                        System.Console.WriteLine("  Methord:" + minfo);
                        foreach (System.Reflection.ParameterInfo pinfo in minfo.GetParameters())
                        {
                            System.Console.WriteLine("   Parameters:" + pinfo);
                        }

                    }
                }
            }
        }

        private static string AssPath = @"Binder";
        private static string TypeName = "ChapterSeven.Calc";

        /// <summary>
        /// System.Activator创建编译时未知的类的实例
        /// </summary>
        public static void CreateObj_Activator()
        {
            //直接指定路径，并使用load方法加载强名称的程序集，出现“未能找到程序集”错误
            //System.Reflection.Assembly ass1 = System.Reflection.Assembly.Load(@"D:\Project\NET2.0实战笔记\CSharp_NET2_Practical\ConsoleTest\7-反射、后期绑定与attribute\BinderWithKeyfile.dll");
            //在程序目录中使用load方法加载强名称的程序集，出现“未能找到程序集”错误
            //System.Reflection.Assembly ass2 = System.Reflection.Assembly.Load("BinderWithKeyfile.dll");

            /*
             * 错误原因：去掉程序集的扩展名称即可。
             */

            //使用Assembly.Load加载程序集的顺序是怎样的呢？
            //首先它会去全局程序集缓存查找，然后到应用程序的根目录查找，最后会到应用程序的私有路径查找。
            System.Reflection.Assembly ass3 = System.Reflection.Assembly.Load("Binder");
            Type type3 = ass3.GetType(TypeName);
            object obj3 = System.Activator.CreateInstance(type3);
            //LoadFrom方法中需要制定程序集的完整路径包括扩展名
            System.Reflection.Assembly ass = System.Reflection.Assembly.LoadFrom(@"D:\Project\NET2.0实战笔记\CSharp_NET2_Practical\ConsoleTest\7-反射、后期绑定与attribute\Binder.dll");
            Type type = ass.GetType(TypeName);
            object obj = System.Activator.CreateInstance(type);
        }

        /// <summary>
        ///System.Domain创建编译时未知的类的实例
        /// </summary>
        public static void CreateObj_AppDomain()
        {
            //指定程序集名称即可，不需要指定扩展名称
            object obj = System.AppDomain.CurrentDomain.CreateInstanceAndUnwrap("Binder", TypeName);
        }

        /// <summary>
        ///System.Reflection.ConstructorInfo 创建编译时未知的类的实例
        /// </summary>
        public static void CreateObj_Reflection()
        {
            System.Reflection.Assembly ass = System.Reflection.Assembly.Load(AssPath);
            Type type = ass.GetType(TypeName);
            System.Reflection.ConstructorInfo ctorInfo = type.GetConstructor(new Type[0]);
            object obj=ctorInfo.Invoke(new object[0]);
        }

        /// <summary>
        /// System.Type类的InvokeMember创建编译时未知的类的实例
        /// </summary>
        public static void CreateObj_Type()
        {
            // System.Type类的InvokeMember创建编译时未知的类的实例
            //指定
            System.Reflection.Assembly ass = System.Reflection.Assembly.Load(AssPath);
            Type type = ass.GetType(TypeName);
            Object obj=type.InvokeMember(
                null //don't need to provider a name for calling a constructor
                ,System.Reflection.BindingFlags.CreateInstance
                ,null
                ,null
                ,new Object[0]);
            //obj引用实例
        }

        /// <summary>
        /// 通过后期绑定技术创建实例，并调用实例的方法
        /// </summary>
        public static void InvokeMethod()
        {
            //指定程序集名称即可，不需要指定扩展名称
            object obj = System.AppDomain.CurrentDomain.CreateInstanceAndUnwrap("Binder", TypeName);

            Type type = obj.GetType();
            object[] paras=new object[2];
            paras[0] = 7;
            paras[1] = 9;
            int result= (int)type.InvokeMember(
                "Sum"
                , System.Reflection.BindingFlags.InvokeMethod
                , null
                , obj
                , paras);

            System.Console.WriteLine("sum result is:{0}",result);
        }
    }
}